package frame

import (
	"fmt"
	"io"
	"log"
	"os"
	"sync"
	"time"

	"gitee.com/go-mao/mao/libs/try"
	xlog "xorm.io/xorm/log"
)

type LogLevel int

const (
	LOG_DEBUG LogLevel = iota
	LOG_INFO
	LOG_WARNING
	LOG_ERR
	LOG_OFF
	LOG_UNKNOWN
)

type MaoLogInterface interface {
	Debug(v ...any)
	Warn(v ...any)
	Info(v ...any)
	Error(v ...any)
	Debugf(format string, v ...any)
	Warnf(format string, v ...any)
	Infof(format string, v ...any)
	Errorf(format string, v ...any)
}

type logDomain struct {
	sync.Mutex
	date    string
	server  *Server
	file    io.Writer
	DEBUG   *log.Logger
	ERR     *log.Logger
	INFO    *log.Logger
	WARN    *log.Logger
	level   LogLevel
	showSQL bool
}

func (this *logDomain) init() {
	level := this.server.config.Section("server").Key("log-level").MustString("unknow")
	switch level {
	case "debug":
		this.level = LOG_DEBUG
	case "info":
		this.level = LOG_INFO
	case "warn":
		this.level = LOG_WARNING
	case "err":
		this.level = LOG_ERR
	case "off":
		this.level = LOG_OFF
	default:
		this.level = LOG_UNKNOWN
	}
	flag := log.Ldate | log.Lmicroseconds
	this.DEBUG = log.New(this, "[debug] ", flag)
	this.ERR = log.New(this, "[error]  ", flag)
	this.INFO = log.New(this, "[info]  ", flag)
	this.WARN = log.New(this, "[warn]  ", flag)
}

func (this *logDomain) Write(v []byte) (n int, err error) {
	var date = time.Now().Format("2006.01.02")
	if this.date != date {
		file, err := os.OpenFile(fmt.Sprintf("%s/%s.log", DIR_LOGS, date), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0660)
		if err != nil {
			try.Throw(CODE_WARN, "日志文件创建失败：", err.Error())
		}
		this.file = file
		this.date = date
	}
	return this.file.Write(v)
}

func (this *logDomain) Error(v ...interface{}) {
	if this.level <= LOG_ERR {
		fv := fmt.Sprintln(v...)
		this.autoDebugPrint(fv)
		_ = this.ERR.Output(2, fv)
	}
}

func (this *logDomain) Errorf(format string, v ...interface{}) {
	if this.level <= LOG_ERR {
		fv := this.sprintf(format, v...)
		this.autoDebugPrint(fv)
		_ = this.ERR.Output(2, fv)
	}
}

// Debug implement ILogger
func (this *logDomain) Debug(v ...interface{}) {
	if this.level <= LOG_DEBUG {
		fv := fmt.Sprintln(v...)
		this.autoDebugPrint(fv)
		_ = this.DEBUG.Output(2, fv)
	}
}

func (this *logDomain) Debugf(format string, v ...interface{}) {
	if this.level <= LOG_DEBUG {
		fv := this.sprintf(format, v...)
		this.autoDebugPrint(fv)
		_ = this.DEBUG.Output(2, fv)
	}
}

func (this *logDomain) Info(v ...interface{}) {
	if this.level <= LOG_INFO {
		fv := fmt.Sprintln(v...)
		this.autoDebugPrint(fv)
		_ = this.INFO.Output(2, fv)
	}
}

func (this *logDomain) Infof(format string, v ...interface{}) {
	if this.level <= LOG_INFO {
		fv := this.sprintf(format, v...)
		this.autoDebugPrint(fv)
		_ = this.INFO.Output(2, fv)
	}
}

func (this *logDomain) Warn(v ...interface{}) {
	if this.level <= LOG_WARNING {
		fv := fmt.Sprintln(v...)
		this.autoDebugPrint(fv)
		_ = this.WARN.Output(2, fv)
	}
}

func (this *logDomain) Warnf(format string, v ...interface{}) {
	if this.level <= LOG_WARNING {
		fv := this.sprintf(format, v...)
		this.autoDebugPrint(fv)
		_ = this.WARN.Output(2, fv)
	}
}

// 实现xorm的logger接口
func (this *logDomain) Level() xlog.LogLevel {
	return xlog.LogLevel(this.level)
}

// 实现xorm的logger接口
func (this *logDomain) SetLevel(l xlog.LogLevel) {
	this.level = LogLevel(l)
}

// 实现xorm的logger接口
func (this *logDomain) ShowSQL(show ...bool) {
	if len(show) == 0 {
		this.showSQL = true
		return
	}
	this.showSQL = show[0]
}

// 实现xorm的logger接口
func (this *logDomain) IsShowSQL() bool {
	return this.showSQL
}

// 格式化日输出
func (this *logDomain) sprintf(format string, a ...any) string {
	return fmt.Sprintf(format, a...)
}

func (this *logDomain) autoDebugPrint(v string) {
	if this.server.config.RunMode != string(RUN_MODE_PRODUCT) {
		fmt.Println(v)
	}
}
